package com.google.code.wicket.auth.component.marker;

import java.util.Collection;

import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.RestartResponseAtInterceptPageException;
import org.apache.wicket.Session;

import com.google.code.wicket.auth.component.value.provider.session.SessionLoginProvider;

/**
 * An extension of {@link SessionBasedMarkerSupport} that will redirect to a
 * specified login page if the specified login provider says the user isn't
 * logged in yet. Will fail with NPEs if no session is available.
 * 
 * @param <S>
 *            session type
 * @param <T>
 *            privilege type
 * @param <P>
 *            login page type
 */
public abstract class SessionBasedMarkerSupportWithLoginPage<S extends Session, T, P extends Page>
        extends SessionBasedMarkerSupport<S, T> {

    private final SessionLoginProvider<S> loginProvider;
    private final Class<P> loginPageClass;

    /**
     * Constructor with a Login provider, a runtime type for privileges and a
     * login page.
     * 
     * @param loginProvider
     * @param privilegeType
     * @param loginPage
     */
    public SessionBasedMarkerSupportWithLoginPage(
            final SessionLoginProvider<S> loginProvider,
            final Class<T> privilegeType, final Class<P> loginPage) {
        super(privilegeType);
        this.loginProvider = loginProvider;
        this.loginPageClass = loginPage;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean doHandleMissingValues(final Component component,
            final Collection<T> missingValues) {
        final S session = this.getSession();
        if (!this.loginProvider.isLoggedIn(session)) {
            throw new RestartResponseAtInterceptPageException(
                    this.loginPageClass);
        }
        return this.doHandleMissingValuesForLoggedInSession(session, component,
                missingValues);
    }

    /**
     * Handle missing privilege values.
     * 
     * @param session
     *            the user session (not null)
     * @param component
     *            the component (not null)
     * @param missingValues
     *            the missing privileges (not empty)
     * @return true if handled successfully
     * @see #handleComponent(Component)
     */
    protected abstract boolean doHandleMissingValuesForLoggedInSession(
            S session, Component component, Collection<T> missingValues);

}
